# 列表和元组
# 列表和元组相似 唯一区别就是列表可以修改 而元组不能修改

# # 列表的创建
# a = []
# print(type(a))
# b = list()
# print(type(b))
# # 列表指定初始值
# c = [1, 2, 3, 4]
# print(c)
# # 一个列表里面可以存放不同类型的变量
# d = [1, 'hello', [4, 5, 6], True]
# print(d)
# # 使用下标访问列表
# print(d[0])
# print(d[1])
# print(d[2])
# # 使用下标修改列表
# d[0] = 10000
# print(d)
# # 下标超过有效范围会报错
# # d[100] = 1
# # 使用内建函数len()可以计算列表的长度 和字符串类似 len()函数可以接收很多类型的参数 这是因为动态类型
# print(len(a))
# print(len(b))
# print(len(c))
# print(len(d))
# # python中的下标可以是负数 表示的位置是列表的长度加上这个负数所在的下标
# e = [1,2,3,4,5,6,7]
# print(e[-1]) # 的等价于print(e[len[e] - 1])
# print(e[-2])
# print(e[-3])
# print(e[-4])

######################################################################################

# # 列表的切片
# # [index1:index2]内指定切片的范围 左闭右开
# # 这两个下标都可以省略 省略前面表示从 0 下标开始 省略后面表示一直取到最后一个下标
# # 切片是一个很高效的操作 这是因为切片并不涉及到数据的拷贝 只是取出原来列表中的一部分
# a = [1, 2, 3, 4, 5, 6]
# print(a[1:3])
# print(a[:4])
# print(a[4:])
# print(a[:])
# # 当然可以搭配负数下标进行操作
# print(a[1:-1])
# # 切片可以指定步长 就是range一样 也就是第三个操作数
# print(a[::2])
# # 当步长为负数的时候表示从后面开始切片
# print(a[::-1])
# # 当切片左边范围超过列表合法下标之后 不会报错 而是直接将后面数据取尽
# print(a[0:1000])

######################################################################################
# 列表的遍历

# # 可以使用for循环
# a = [1, 2, 3, 4, 5, 6 ,7, 8, 9, 0]
# # 可直接使用a
# for elem in a:
#     print(elem)
#     elem += 10
# print(a)
# # 或者使用下标遍历
# for i in range(0, len(a)):
#     print(a[i])
#     a[i] = a[i] + 10
# print(a)
# # elem只是另外开的一个变量 和列表a不相干 只是一直覆盖记录了列表a的值 所以修改elem元素不影响列表a
# # 若是拿着下标修改 则a中的元素会被改变
#
# # 使用while循环遍历
# j = 0
# while j < len(a):
#     print(a[j])
#     j += 1

######################################################################################

# # 列表插入元素
# # 使用append方法在列表后面添加元素 append不是一个函数 而是对象内部定义的方法
# a = [1, 2, 3, 4]
# a.append('hello')
# print(a)
# # 还可以使用insert方法 往列表的任意位置插入元素
# a.insert(1, 'next1')
# print(a)
# # 若是超出了合法下标位置 那么插入就是相当于append
# a.insert(100, 'tail')
# print(a)

######################################################################################
# # 查找列表中元素的位置
# a = [1, 2, 3, 4]
# # 使用in判断元素在列表中存不存在
# print(1 in a)
# print(4 in a)
# print(10 in a)
# # 使用index查看一个元素在列表中的下标
# print(a.index(1))
# print(a.index(2))
# print(a.index(4))
# print(a.index(10)) # 不存在的元素使用index方法会出错

######################################################################################
# # 列表中删除元素
# a = [1, 2, 3, 4]
# # 使用pop()删除列表最后一个元素
# # pop()可以传一个下标过去 指定删除的下标的元素
# a.pop()
# print(a)
# a.pop(2)
# print(a)
# # 使用remove可以指定删除一个值
# b = ['aa', 'bb', 'cc']
# b.remove('bb')
# print(b)

######################################################################################
# # 列表的拼接
# # 使用 + 号拼接 原列表没有发生变化 生成了一个新列表
# a = [1,2,3,4]
# b = [5,6,7,8]
# c = a + b
# print(a)
# print(b)
# print(c)
# # 使用extend拼接 此时对原列表进行了改变 没有生成中间临时列表
# c = a.extend(b) # 打印None 这是因为这个方法没有返回值 写一个接收返回值默认为None 相当于C++中的nullptr
# print(c)
# print(a)
# print(b)
# # 使用c += d 等价于 c = c + d 此时生成了临时中间列表并且还有一步赋值操作 赋值之后还有一个释放操作
# # 而extend直接拼接没有任何的中间过程 效率相比而言更高效
# c = [1,2,3,4]
# d = [5,6,7,8]
# c += d
# print(c)
# print(d)
######################################################################################

# 元组
# 元组和列表类似 就是元组一旦定义出来就不能被修改

# 元组的创建
# a = ()
# print(type(a))
# b = tuple()
# print(type(b))
# 创建元组指定初始值 元组中也是可以存不同类型数据的
a = (1, 2, 3, 4)
print(a)
b = (1, 'bbb', (5, 6, 7), 1.1198)
print(b)
# 通过下标访问元组中的元素
print(a[0])
print(b[-1])
# 使用循环遍历元组
for elem in b:
    print(elem)
# 使用in判断数据在一个元组中存不存在 使用index方法查找元素在元组中的下标
print(1 in b)
print('aaa' in b)
print('bbb' in b)

print(b.index('bbb'))
print(b.index((5, 6, 7)))

# + 拼接元组
c = a + b
print(c)

# 元组不支持修改操作
# a[1] = 100 报错 TypeError: 'tuple' object does not support item assignment
# 对应的append、pop、extend方法也不能使用

# 当一次性对多个遍历进行赋值的时候实际上是按照元组的方式工作的
def func():
    x = 10
    y = 20
    return x, y

x, y = func()
print(type((x, y)))
print(type(func()))